package com.xbongbong.saas.analytical.impl;

import com.alibaba.fastjson.JSONArray;
import com.alibaba.fastjson.JSONObject;
import com.xbongbong.paas.constant.TimeConstant;
import com.xbongbong.paas.domain.entity.ext.PaasFormDataEntityExt;
import com.xbongbong.paas.elasticsearch.model.PaasEsModel;
import com.xbongbong.paas.elasticsearch.model.PaasFormDataEsModel;
import com.xbongbong.paas.enums.DelEnum;
import com.xbongbong.paas.enums.IndexTypeEnum;
import com.xbongbong.paas.pojo.dto.ValidateDataDTO;
import com.xbongbong.paas.toolbox.exception.XbbException;
import com.xbongbong.paas.toolbox.util.DateTimeUtil;
import com.xbongbong.paas.toolbox.wrap.UserVO;
import com.xbongbong.pro.enums.CommunicatePlanNotifyTypeEnum;
import com.xbongbong.pro.enums.ErrorCodeEnum;
import com.xbongbong.pro.enums.SaasMarkEnum;
import com.xbongbong.pro.enums.errorcodes.ContactErrorCodeEnum;
import com.xbongbong.pro.enums.errorcodes.CustomerCommunicateErrorCodeEnum;
import com.xbongbong.pro.enums.errorcodes.ClueErrorCodeEnum;
import com.xbongbong.pro.enums.errorcodes.CustomerErrorCodeEnum;
import com.xbongbong.pro.enums.errorcodes.SystemErrorCodeEnum;
import com.xbongbong.pro.enums.permission.enums.ProPermissionAliasEnum;
import com.xbongbong.pro.formdata.pojo.SaasNeedRedundantAttrPojo;
import com.xbongbong.saas.analytical.SaasValidateAnalyticalService;
import com.xbongbong.saas.constant.BasicConstant;
import com.xbongbong.saas.domain.entity.ext.ClueEntityExt;
import com.xbongbong.saas.domain.entity.ext.CustomerEntityExt;
import com.xbongbong.saas.enums.XbbRefTypeEnum;
import com.xbongbong.saas.enums.base.CommunicateBaseEnum;
import com.xbongbong.saas.enums.business.ContactEnum;
import com.xbongbong.saas.enums.business.CustomerCommunicateEnum;
import com.xbongbong.saas.enums.business.CustomerManagementEnum;
import com.xbongbong.saas.help.SaasDataInitHelp;
import com.xbongbong.saas.help.SaveFormatHelp;
import com.xbongbong.saas.model.ClueModel;
import com.xbongbong.saas.model.CustomerModel;
import com.xbongbong.saas.toolbox.help.FastJsonHelper;
import com.xbongbong.sys.domain.entity.UserEntity;
import com.xbongbong.sys.model.UserModel;
import org.apache.commons.collections4.CollectionUtils;
import org.apache.commons.lang3.StringUtils;
import org.springframework.stereotype.Service;

import javax.annotation.Resource;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collections;
import java.util.List;
import java.util.Map;
import java.util.Objects;

import static com.xbongbong.saas.toolbox.help.FastJsonHelper.getIntegerOrDefaultFromFormData;

/**
 * @author 吴峰
 * @date 2021/07/15 17:15
 */
@Service("communicateAnalyticalServiceImpl")
public class CustomerCommunicateValidateAnalyticalServiceImpl implements SaasValidateAnalyticalService {
    
    @Resource
    private PaasFormDataEsModel paasFormDataEsModel;
    @Resource
    private CustomerModel customerModel;
    @Resource
    private ClueModel clueModel;
    @Resource
    private UserModel userModel;
    @Resource
    private PaasEsModel paasEsModel;

    @Override
    public List<Integer> type() {
        return Arrays.asList(XbbRefTypeEnum.CUSTOMER_COMMUNICATE.getCode());
    }

    @Override
    public void analyticalData(ValidateDataDTO validateDataDTO) throws XbbException {
        beforeSave(validateDataDTO);
    }
    
    public void beforeSave(ValidateDataDTO validateDataDTO) throws XbbException {
        String corpid = validateDataDTO.getCorpid();
        JSONObject data = validateDataDTO.getData();
        String userId = validateDataDTO.getUserId();
        Long dataId = validateDataDTO.getDataId();
        boolean isNew = false;
        if (dataId == null || dataId == 0) {
            isNew = true;
        }
        SaveFormatHelp.formatLinkBusiness4Save(data, CustomerCommunicateEnum.CUSTOMER_NAME.getAttr(), CustomerCommunicateEnum.CUSTOMER_NAME_LINK_TEXT.getAttr(), CustomerCommunicateEnum.CUSTOMER_NAME.getFieldType());
        SaveFormatHelp.formatLinkBusiness4Save(data, CustomerCommunicateEnum.CONTACT_ARRAY.getAttr(), CustomerCommunicateEnum.CONTACT_NAME_LINK_TEXT.getAttr(), CustomerCommunicateEnum.CONTACT_ARRAY.getFieldType());
        SaveFormatHelp.formatCommunicateBusiness4Save(data, CustomerCommunicateEnum.COMMUNICATE_BUSINESS.getAttr(), CustomerCommunicateEnum.COMMUNICATE_BUSINESS_TYPE.getAttr(), CustomerCommunicateEnum.COMMUNICATE_BUSINESS_LINK_TEXT.getAttr());
        SaveFormatHelp.formatLinkBusiness4Save(data, CustomerCommunicateEnum.FINISH_COMMUNICATE_PLAN_ID.getAttr(), CustomerCommunicateEnum.FINISH_COMMUNICATE_PLAN_LINK_TEXT.getAttr(), CustomerCommunicateEnum.FINISH_COMMUNICATE_PLAN_ID.getFieldType());
        // 时间校验
        checkData(data, isNew);

        Long customerId = FastJsonHelper.getLongFromFormData(data, CustomerCommunicateEnum.CUSTOMER_NAME.getAttr());
        boolean clueDetailAddOrSaveClue = false;
        Integer businessType = getIntegerOrDefaultFromFormData(data, CustomerCommunicateEnum.COMMUNICATE_BUSINESS_TYPE.getAttr(), BasicConstant.ZERO);
        SaasNeedRedundantAttrPojo saasNeedRedundantAttrPoJo = validateDataDTO.getSaasNeedRedundantAttrPoJo();
        if ((Objects.nonNull(saasNeedRedundantAttrPoJo) && Objects.equals(saasNeedRedundantAttrPoJo.getParentBusinessType(), XbbRefTypeEnum.CLUE.getCode())) || Objects.equals(businessType, XbbRefTypeEnum.CLUE.getCode())) {
            // 线索关联新建或者保存跟进业务是线索的时候，不校验关联客户，因为他不展示展示这个字段
            clueDetailAddOrSaveClue = true;
        }
        // 公海池客户新增跟进记录校验
        checkCustomerPublicPermission(corpid,validateDataDTO.getLoginUser(),data,clueDetailAddOrSaveClue);
        if (!clueDetailAddOrSaveClue) {
            CustomerEntityExt customerEntityExt = customerModel.getByKey(customerId, corpid);
            if (customerEntityExt == null) {
                throw new XbbException(CustomerErrorCodeEnum.API_ERROR_201001);
            } else if (customerEntityExt.getDel().equals(1)) {
                throw new XbbException(CustomerErrorCodeEnum.API_ERROR_201001);
            }
        } else {
            Long clueId = FastJsonHelper.getLongOrDefaultFromFormData(data, CustomerCommunicateEnum.COMMUNICATE_BUSINESS.getAttr(), -1L);
            ClueEntityExt clueEntity = clueModel.getByKey(clueId, corpid);
            if (clueEntity == null) {
                throw new XbbException(ClueErrorCodeEnum.API_ERROR_1110023);
            } else if (clueEntity.getDel().equals(DelEnum.DELETE.getDel())) {
                throw new XbbException(ClueErrorCodeEnum.API_ERROR_1110023);
            }
        }
        JSONArray contactArr = FastJsonHelper.getJsonArrOrDefaultFromFormData(data, CustomerCommunicateEnum.CONTACT_ARRAY.getAttr(), new JSONArray());
        List<Long> contactIds = contactArr.toJavaList(Long.class);
        if (Objects.nonNull(contactIds) && CollectionUtils.isNotEmpty(contactIds)) {
            List<PaasFormDataEntityExt> paasFormDataEntityExts = paasEsModel.getByIdList(contactIds, corpid, SaasMarkEnum.SAAS.getCode(), XbbRefTypeEnum.CONTACT.getCode(), new ArrayList<>(), IndexTypeEnum.IDX_SAAS_CONTACT);
            if (contactIds.size() != paasFormDataEntityExts.size()) {
                throw new XbbException(ContactErrorCodeEnum.API_ERROR_204006);
            }
            for (PaasFormDataEntityExt paasFormDataEntityExt : paasFormDataEntityExts) {
                Long linkCustomerId = FastJsonHelper.getLongOrDefaultFromFormData(paasFormDataEntityExt.getData(), ContactEnum.CUSTOMER_NAME.getAttr(), 0L);
                if (!Objects.equals(linkCustomerId, customerId)) {
                    throw new XbbException(ContactErrorCodeEnum.API_ERROR_204007);
                }
            }
        }
        if (isNew) {
            data.put(CustomerCommunicateEnum.AUTO_GEN.getAttr(), 0);
            if (Objects.nonNull(data.get(CustomerCommunicateEnum.CREATOR_ID.getAttr()))) {
                userId = data.getString(CustomerCommunicateEnum.CREATOR_ID.getAttr());
            }
            UserEntity userEntity = userModel.getByKeyIngoreDel(userId, corpid);
            if (Objects.isNull(userEntity)) {
                throw new XbbException(SystemErrorCodeEnum.API_ERROR_100004);
            }
            if (Objects.nonNull(userEntity)) {
                data.put(CustomerCommunicateEnum.USER_ID.getAttr(), userEntity.getUserId());
                data.put(CustomerCommunicateEnum.USER_NAME.getAttr(), userEntity.getName());
                data.put(CustomerCommunicateEnum.USER_AVATAR.getAttr(), Collections.singletonList(userEntity.getAvatar()));
            }
        }
        for (Map.Entry<String,Object> entry : SaasDataInitHelp.initCustomerCommunicate().entrySet()){
            SaasDataInitHelp.antDataSet(data,entry.getKey(),entry.getValue());
        }
        validateDataDTO.setData(data);
    }

    /**
     * 校验时间
     *
     * @param data 跟进记录数据
     * @param isNew 是否新建
     * @throws XbbException 业务类型错误
     * @author long.rao
     * @date 2019-05-27 15:06
     */
    private void checkData(JSONObject data, boolean isNew) throws XbbException {
        Long communicateTime = FastJsonHelper.getLongOrDefaultFromFormData(data, CustomerCommunicateEnum.COMMUNICATE_TIME.getAttr(), 0L);
        if (Objects.equals(communicateTime, 0L)) {
            throw new XbbException(CustomerCommunicateErrorCodeEnum.API_ERROR_206004);
        }
        if (communicateTime > DateTimeUtil.getInt()){
            throw new XbbException(CustomerCommunicateErrorCodeEnum.API_ERROR_206008);
        }
        Integer notifyType = getIntegerOrDefaultFromFormData(data, CustomerCommunicateEnum.NOTIFY_TYPE.getAttr(), CommunicatePlanNotifyTypeEnum.NO_NOTIFY.getCode());
        Long notifyTime = 0L;
        Long nextCommunicateTime = FastJsonHelper.getLongOrDefaultFromFormData(data, CustomerCommunicateEnum.NEXT_COMMUNICATE_TIME.getAttr(), 0L);
        Integer ifRemind = getIntegerOrDefaultFromFormData(data, CustomerCommunicateEnum.IF_REMIND.getAttr(), BasicConstant.ZERO);
        CommunicatePlanNotifyTypeEnum communicatePlanNotifyTypeEnum = CommunicatePlanNotifyTypeEnum.getByCode(notifyType);
        if (Objects.equals(ifRemind, BasicConstant.ONE)) {
            switch (communicatePlanNotifyTypeEnum) {
                case ADVANCE_ONE_QUARTER_HOUR:
                    notifyTime = nextCommunicateTime - TimeConstant.SECONDS_PER_MINUTE * 15;
                    break;
                case ADVANCE_ONE_HOUR:
                    notifyTime = nextCommunicateTime - TimeConstant.SECONDS_PER_HOUR;
                    break;
                case ADVANCE_ONE_DAY:
                    notifyTime = nextCommunicateTime - TimeConstant.SECONDS_PER_DAY;
                    break;
                case ADVANCE_THREE_DAY:
                    notifyTime = nextCommunicateTime - TimeConstant.SECONDS_PER_DAY * 3;
                    break;
                case ADVANCE_ONE_WEEK:
                    notifyTime = nextCommunicateTime - TimeConstant.SECONDS_PER_WEEK;
                    break;
                case CUSTOM_TIME:
                    notifyTime = FastJsonHelper.getLongOrDefaultFromFormData(data, CustomerCommunicateEnum.NOTIFY_TIME.getAttr(), 0L);
                    break;
                default:
                    notifyTime = nextCommunicateTime;
                    break;
            }
            if (isNew) {
                if (notifyTime == null || notifyTime <= DateTimeUtil.getInt()) {
                    throw new XbbException(CustomerCommunicateErrorCodeEnum.API_ERROR_206009);
                }
                if (notifyTime > nextCommunicateTime) {
                    throw new XbbException(CustomerCommunicateErrorCodeEnum.API_ERROR_206011);
                }
            }
            data.put(CustomerCommunicateEnum.NOTIFY_TIME.getAttr(), notifyTime);
        }
    }

    /**
     * 校验用户是否有对公海池客户新建跟进的权限
     * @param corpid
     * @param userVO
     * @param data
     * @throws XbbException
     */
    private void checkCustomerPublicPermission(String corpid ,UserVO userVO,JSONObject data,boolean isClue) throws XbbException{
        // 线索新建跟进记录不再校验公海池权限
        if (isClue){
            return;
        }
        try {
            String customerId = FastJsonHelper.getStringFromFormData(data, CommunicateBaseEnum.MAIN_BUSINESS.getAttr());
            if (StringUtils.isEmpty(customerId)) {
                throw new XbbException(CustomerErrorCodeEnum.API_ERROR_201001);
            }
            CustomerEntityExt customerEntityExt = customerModel.getByKey(Long.valueOf(customerId), corpid);
            if (Objects.isNull(customerEntityExt)) {
                throw new XbbException(CustomerErrorCodeEnum.API_ERROR_201001);
            }
            JSONObject customerData = customerEntityExt.getData();
            Integer isPublic = FastJsonHelper.getIntegerFromFormData(customerData,CustomerManagementEnum.IS_PUBLIC.getAttr());
            // 对公海池客户新建跟进记录时判断用户是否具有公海池权限
            if (!Objects.isNull(isPublic) && Objects.equals(isPublic,1)){
                if (!userVO.getPermSet().contains(ProPermissionAliasEnum.CUSTOMER_PUBLIC.getAlias())) {
                    throw new XbbException(CustomerCommunicateErrorCodeEnum.API_ERROR_206014);
                }
            }
        }catch (Exception e){
            throw e;
        }
    }
}
